//
//  RisacTopBar.swift
//  Risac
//
//  Created by remy on 2018/4/25.
//

import UIKit

private typealias ItemViewClosure = (RisacTopBarItem) -> Void

open class RisacTopBar: UIView {
    
    public struct Options {
        /// 背景色
        public var bgColor: UIColor = .white
        /// 视图高度
        public var viewHeight: CGFloat = 44.0
        /// 文字颜色(左,中,右)
        public var textColor: (left: UIColor, center: UIColor, right: UIColor) = (.black, .black, .black)
        /// 字体(左,中,右)
        public var font: (left: UIFont, center: UIFont, right: UIFont) = (UIFont.systemFont(ofSize: 16.0), UIFont.boldSystemFont(ofSize: 17.0), UIFont.systemFont(ofSize: 16.0))
        /// 分隔线颜色
        public var lineColor: UIColor = .black
        /// 中间项布局
        public var centerAlignment: NSTextAlignment = .center
        public init() {}
    }
    private var options: Options
    public static var global: Options = Options()
    /// 内容视图
    public private(set) var contentView: UIView!
    /// 分隔线
    public var bottomLine: UIView!
    /// 视图高度
    public var viewHeight: CGFloat { didSet { triggerLayout(0b101) } }
    /// 中间项布局
    public var centerAlignment: NSTextAlignment { didSet { triggerLayout(0b100) } }
    /// 左侧项
    public var leftItems: [RisacTopBarItem] = [] { didSet { triggerLayout(0b110) } }
    /// 右侧项
    public var rightItems: [RisacTopBarItem] = [] { didSet { triggerLayout(0b110) } }
    /// 中间项
    public var centerItem: RisacTopBarItem? { didSet { triggerLayout(0b110) } }
    /// 是否监听横竖屏切换
    public var handleOrientation: Bool = false {
        didSet {
            NotificationCenter.default.removeObserver(self, name: UIApplication.didChangeStatusBarOrientationNotification, object: nil)
            if handleOrientation {
                NotificationCenter.default.addObserver(self, selector: #selector(self.didChangeOrientation), name: UIApplication.didChangeStatusBarOrientationNotification, object: nil)
            }
        }
    }
    /// 更新规则
    private var layoutFlag: (Bool, Int) = (false, 0)
    
    public init(closure: ((inout Options) -> Void)? = nil) {
        var options = RisacTopBar.global
        closure?(&options)
        self.options = options
        viewHeight = options.viewHeight
        centerAlignment = options.centerAlignment
        super.init(frame: .zero)
        self.backgroundColor = options.bgColor
        contentView = UIView()
        self.addSubview(contentView)
        bottomLine = UIView(frame: .zero, bgColor: options.lineColor)
        self.addSubview(bottomLine)
        refreshWrapLayout()
    }
    
    required public init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    deinit {
        Risac.print("\(self.metaTypeName) has deinit")
    }
    
    @objc private func didChangeOrientation() {
        // 横屏变竖屏时 UIApplication.shared.statusBarFrame 更新延迟,因此延迟执行
        triggerLayout(0b101)
    }
    
    public func triggerLayout(_ flag: Int) {
        self.layoutFlag.1 |= flag
        if !layoutFlag.0 {
            layoutFlag.0 = true
            QueueTask.main { [weak self] in
                self?.refreshLayout()
            }
        }
    }
    
    private func refreshLayout() {
        // 容器布局
        if layoutFlag.1 & 0b001 > 0 {
            refreshWrapLayout()
        }
        // 内容渲染
        if layoutFlag.1 & 0b010 > 0 {
            contentView.removeAllSubviews()
            let closure: (RisacTopBarItem, UIFont, UIColor) -> Void = {
                let sectionView = UIView(frame: CGRect(x: 0.0, y: $0.margin.top, width: 0.0, height: self.contentView.height - $0.margin.top - $0.margin.bottom))
                if $0.type != .group, let action = $0.action as? UITapGestureRecognizer {
                    sectionView.addGestureRecognizer(action)
                }
                sectionView.backgroundColor = $0.bgColor ?? .clear
                $0.sectionView = sectionView
                self.drawItemView(item: $0, closure: self.drawItemClosure(sectionView, defaultFont: $1, defaultColor: $2))
            }
            for item in leftItems {
                closure(item, options.font.left, options.textColor.left)
            }
            for item in rightItems {
                closure(item, options.font.right, options.textColor.right)
            }
            if let item = centerItem {
                closure(item, options.font.center, options.textColor.center)
            }
        }
        // 内容布局
        if layoutFlag.1 & 0b100 > 0 {
            refreshContentLayout()
        }
        layoutFlag.0 = false
    }
    
    private func drawItemView(item: RisacTopBarItem, closure: ItemViewClosure) {
        if item.type == .group {
            item.group.forEach {
                drawItemView(item: $0, closure: closure)
            }
        } else {
            closure(item)
        }
    }
    
    private func drawItemClosure(_ wrap: UIView, defaultFont: UIFont, defaultColor: UIColor) -> ItemViewClosure {
        self.contentView.addSubview(wrap)
        return { (item) in
            if let text = item.text, !text.isEmpty {
                let label = UILabel(text: text, textColor: item.textColor ?? defaultColor, font: item.font ?? defaultFont)
                label.origin = CGPoint(x: wrap.width + item.inset.left, y: item.inset.top)
                label.size = CGSize(width: text.sac.width(font: label.font).rounded(.up), height: wrap.height - label.top - item.inset.bottom)
                wrap.addSubview(label)
                item.itemView = label
            } else if let attr = item.attr, attr.length > 0 {
                let label = UILabel()
                label.attributedText = attr
                label.origin = CGPoint(x: wrap.width + item.inset.left, y: item.inset.top)
                label.size = CGSize(width: attr.sac.width().rounded(.up), height: wrap.height - label.top - item.inset.bottom)
                wrap.addSubview(label)
                item.itemView = label
            } else if let image = item.image {
                let imageView = UIImageView()
                imageView.origin = CGPoint(x: wrap.width + item.inset.left, y: item.inset.top)
                imageView.size = CGSize(width: image.size.width, height: wrap.height - imageView.top - item.inset.bottom)
                imageView.contentMode = .scaleAspectFit
                imageView.image = image
                wrap.addSubview(imageView)
                item.itemView = imageView
            }
            wrap.width += item.inset.left + (item.itemView?.width ?? 0.0) + item.inset.right
            item.sectionView = wrap
        }
    }
    
    public func refreshWrapLayout() {
        self.frame = CGRect(x: 0.0, y: 0.0, width: UIScreen.width, height: self.viewHeight + Size.topExtraHeight)
        contentView.frame = CGRect(x: 0.0, y: Size.topExtraHeight, width: self.width, height: self.viewHeight)
        bottomLine.frame = CGRect(x: 0.0, y: self.height - Size.onePixel, width: self.width, height: Size.onePixel)
    }
    
    public func refreshContentLayout() {
        var leftSpace: CGFloat = 0.0
        leftItems.forEach {
            guard let section = $0.sectionView else { return }
            section.left = leftSpace + $0.margin.left
            leftSpace = section.right + $0.margin.right
        }
        var rightSpace: CGFloat = 0.0
        rightItems.forEach {
            guard let section = $0.sectionView else { return }
            section.right = contentView.width - rightSpace - $0.margin.right
            rightSpace = contentView.width - section.left - $0.margin.left
        }
        if let item = centerItem, let section = item.sectionView {
            let centerWidth = max(contentView.width - leftSpace - rightSpace - item.margin.left - item.margin.right, 0.0)
            if section.width < centerWidth {
                let offsetMaxX = centerWidth - section.width
                if centerAlignment == .center {
                    let offsetX = max(min((offsetMaxX - leftSpace - item.margin.left + rightSpace + item.margin.right) / 2.0, offsetMaxX), 0.0)
                    section.left = leftSpace + item.margin.left + offsetX
                } else if centerAlignment == .left {
                    section.left = leftSpace + item.margin.left
                } else if centerAlignment == .right {
                    section.left = leftSpace + item.margin.left + offsetMaxX
                }
            } else {
                section.left = leftSpace + item.margin.left
                section.width = centerWidth
                if item.type == .group {
                    item.group.forEach {
                        guard let itemView = $0.itemView else { return }
                        if itemView.left >= centerWidth {
                            itemView.width = 0.0
                        } else if itemView.right + $0.inset.right > centerWidth {
                            itemView.width = max(centerWidth - itemView.left - $0.inset.right, 0.0)
                        }
                    }
                } else {
                    if let itemView = item.itemView {
                        itemView.width = max(centerWidth - itemView.left - item.inset.right, 0.0)
                    }
                }
            }
        }
    }
}
